<template>
    <div
      class="terminal"
      v-loading="loading"
      :element-loading-text="loadingText"
      element-loading-spinner="el-icon-loading"
      element-loading-background="rgba(0, 0, 0, 0.6)">
    <terminal
      :name="socketURI"
      :id="socketURI"
      :ref='socketURI'
      @exec-cmd="onExecCmd"
      :drag-conf="dragConf"
      :show-header="false"
      class="terminal-box">
    </terminal>
  </div>
</template>

<script>
import Terminal,{api as TerminalApi}  from "vue-web-terminal";
  export default {
    name:'VueTerminal',
    props: {
      socketURI: {
        type: String,
        default: ''
      },
      id: {
        type: String,
        default: ''
      },
    },
    data() {
      return {
        term: null,
        socket: '',
        count: 0,
        accessToken: 'token',
        loading: true,
        loadingText: '初始化……',
        cmdStore: [],
        dragConf: {
          width: "80%",
          height: "65%"
        }
      }
    },
    mounted() {
      this.initSocket()
    },
    beforeDestroy() {
      this.socket && this.socket.close();
    },
    methods: {
      initSocket () {
        // 2.webSocket初始化
        if (this.socketURI === '') return;
        this.socket = new WebSocket(this.socketURI);
        this.socketOnOpen()
        this.socketOnMessage()
        this.socketOnClose()
        this.socketOnError()
      },
      onExecCmd(key, command, success, failed) {
        this.socket.send(
          JSON.stringify({
              data: JSON.stringify({ ctlMsg: key }),
              type: 'CtlMsg'
          })
        );
        success()
      },
      socketOnMessage () {
        this.socket.onmessage = (e) => {
          const data = JSON.parse(e.data);
          switch(data.type){
            case 'Status':
              const sshStatus = JSON.parse(data.data).sshStatus
              const msg = JSON.parse(data.data).msg
              this.loadingText = msg
              if(sshStatus === 'CONNECTED'){
                // 成功
                this.loading = false
              }else if(sshStatus === 'CONNECTING' || sshStatus === 'INIT'){
                // 初始化，连接中
              }else if(sshStatus === 'ERROR'){
                // 失败
                this.$confirm(`连接失败，是否继续?`, '提示', {
                  confirmButtonText: '继续',
                  cancelButtonText: '取消',
                  type: 'warning'
                }).then(() => {
                  this.initSocket();
                }).catch(() => {
                  this.$message({
                    type: 'info',
                    message: '已取消重连'
                  });
                });
              }else {
                // 结束
                this.socketOnClose()
              }
              break
            case 'TerminalMsg':
              console.log(JSON.parse(data.data).msg)
              TerminalApi.pushMessage(this.socketURI, JSON.parse(data.data).msg)
              break
            default:
            break
          }
        }
      },
      socketOnOpen() {
        this.socket.onopen = () => {
          this.socket.send(JSON.stringify({
              data:JSON.stringify({dataId: this.id}),
              type: 'Conn'
          }))
        }
      },
      socketOnClose() {
        this.socket.onclose = () => {
          TerminalApi.pushMessage(this.socketURI, 'Bye Bye! \r\n$')
        }
      },
      socketOnError() {
        const maxCount = 3;
        this.socket.onerror = () => {
        if (this.count < maxCount) {
          this.count++;
          console.log(`第 ${this.count} 次重连`);
          setTimeout(() => {
            this.initSocket();
          }, 2000);
        } else {
          console.log('重连失败');
          this.$confirm(`${this.count} 次重连失败，是否继续?`, '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          }).then(() => {
            this.initSocket();
          }).catch(() => {
            this.$message({
              type: 'info',
              message: '已取消重连'
            });
          });
        }
        };
      }
    },
    components: {
      Terminal
    },
  }
</script>

<style lang="scss" scoped>
.terminal{
  width:100%;
  height: 100%;
}
</style>
